package com.ruoyi.common.utils;

import com.ruoyi.common.annotation.IdToName;
import com.mybatisflex.core.query.QueryColumn;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.core.row.Row;
import com.mybatisflex.core.service.IService;
import com.mybatisflex.annotation.Table;
import org.springframework.stereotype.Component;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;

import java.lang.reflect.Field;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 名称映射工具类
 * 用于处理ID到名称的转换
 */
@Component
public class NameMappingUtil {

    // 缓存名称映射
    private static final Map<String, String> nameCache = new ConcurrentHashMap<>();
    // 缓存时间记录
    private static final Map<String, Long> cacheTimeMap = new ConcurrentHashMap<>();
    // 缓存表名
    private static final Map<Class<?>, String> tableNameCache = new ConcurrentHashMap<>();

    /**
     * 根据ID获取名称
     */
    public static String getNameById(Class<?> targetEntity, Object id,
                                     String idField, String nameField,
                                     boolean cacheable, long cacheTimeout) {
        if (id == null || StrUtil.isBlank(id.toString())) {
            return "";
        }

        String cacheKey = targetEntity.getSimpleName() + ":" + idField + ":" + id;

        // 检查缓存
        if (cacheable) {
            String cachedName = getNameFromCache(cacheKey, cacheTimeout);
            if (cachedName != null) {
                return cachedName;
            }
        }

        // 查询数据库
        String name = queryNameFromDatabase(targetEntity, id, idField, nameField);

        // 放入缓存
        if (cacheable && StrUtil.isNotBlank(name)) {
            nameCache.put(cacheKey, name);
            cacheTimeMap.put(cacheKey, System.currentTimeMillis());
        }

        return name != null ? name : "";
    }

    /**
     * 从缓存获取名称
     */
    private static String getNameFromCache(String cacheKey, long cacheTimeout) {
        Long cacheTime = cacheTimeMap.get(cacheKey);
        if (cacheTime != null &&
                System.currentTimeMillis() - cacheTime < cacheTimeout * 1000) {
            return nameCache.get(cacheKey);
        }
        return null;
    }

    /**
     * 从数据库查询名称 - 使用 Mybatis-Flex 的正确方法
     */
    @SuppressWarnings("unchecked")
    private static String queryNameFromDatabase(Class<?> targetEntity, Object id,
                                                String idField, String nameField) {
        try {
            // 方法1: 尝试通过 Service 查询
            String serviceName = StrUtil.lowerFirst(targetEntity.getSimpleName()) + "Service";
            Object service = SpringUtil.getBean(serviceName);

            if (service instanceof IService) {
                IService<?> iService = (IService<?>) service;

                // 构建查询条件
                QueryWrapper queryWrapper = QueryWrapper.create()
                        .select(new QueryColumn(nameField))
                        .where(idField + " = ?", id);

                // 使用 getOneAs 方法查询单条记录
                Row row = iService.getOneAs(queryWrapper, Row.class);
                if (row != null) {
                    return row.getString(nameField);
                }
            }
        } catch (Exception e) {
            // 如果通过Service查询失败，尝试直接查询
            return directQuery(targetEntity, id, idField, nameField);
        }

        return null;
    }

    /**
     * 直接查询（备用方案）- 使用反射获取表名
     */
    private static String directQuery(Class<?> targetEntity, Object id,
                                      String idField, String nameField) {
        try {
            // 获取表名
            String tableName = getTableName(targetEntity);
            if (tableName == null) {
                return null;
            }

            QueryWrapper queryWrapper = QueryWrapper.create()
                    .select(nameField)
                    .from(tableName)
                    .where(idField + " = ?", id);

            // 使用 Db.selectOneByQuery 方法
            Row row = com.mybatisflex.core.row.Db.selectOneByQuery(queryWrapper);
            if (row != null) {
                return row.getString(nameField);
            }
        } catch (Exception e) {
            // 记录日志
            System.err.println("直接查询名称失败: " + e.getMessage());
        }
        return null;
    }

    /**
     * 通过反射获取实体类的表名
     */
    private static String getTableName(Class<?> entityClass) {
        return tableNameCache.computeIfAbsent(entityClass, clazz -> {
            Table tableAnnotation = clazz.getAnnotation(Table.class);
            if (tableAnnotation != null && StrUtil.isNotBlank(tableAnnotation.value())) {
                return tableAnnotation.value();
            }
            // 如果没有@Table注解，使用类名转下划线格式
            return StrUtil.toUnderlineCase(clazz.getSimpleName());
        });
    }

    /**
     * 批量获取名称映射（提高性能）
     */
    public static Map<Object, String> getNamesByIds(Class<?> targetEntity, List<Object> ids,
                                                    String idField, String nameField,
                                                    boolean cacheable, long cacheTimeout) {
        Map<Object, String> result = new HashMap<>();
        if (ids == null || ids.isEmpty()) {
            return result;
        }

        List<Object> uncachedIds = new ArrayList<>();

        // 先检查缓存
        for (Object id : ids) {
            if (id == null) continue;

            String cacheKey = targetEntity.getSimpleName() + ":" + idField + ":" + id;
            if (cacheable) {
                String cachedName = getNameFromCache(cacheKey, cacheTimeout);
                if (cachedName != null) {
                    result.put(id, cachedName);
                    continue;
                }
            }
            uncachedIds.add(id);
        }

        // 批量查询未缓存的ID
        if (!uncachedIds.isEmpty()) {
            Map<Object, String> batchResult = batchQueryNames(targetEntity, uncachedIds, idField, nameField);
            result.putAll(batchResult);

            // 更新缓存
            if (cacheable) {
                for (Map.Entry<Object, String> entry : batchResult.entrySet()) {
                    String cacheKey = targetEntity.getSimpleName() + ":" + idField + ":" + entry.getKey();
                    nameCache.put(cacheKey, entry.getValue());
                    cacheTimeMap.put(cacheKey, System.currentTimeMillis());
                }
            }
        }

        return result;
    }

    /**
     * 批量查询名称 - 修正参数传递方式
     */
    @SuppressWarnings("unchecked")
    private static Map<Object, String> batchQueryNames(Class<?> targetEntity, List<Object> ids,
                                                       String idField, String nameField) {
        Map<Object, String> result = new HashMap<>();

        try {
            String serviceName = StrUtil.lowerFirst(targetEntity.getSimpleName()) + "Service";
            Object service = SpringUtil.getBean(serviceName);

            if (service instanceof IService) {
                IService<?> iService = (IService<?>) service;

                // 使用 Mybatis-Flex 的 IN 查询方式
                QueryWrapper queryWrapper = QueryWrapper.create()
                        .select(idField, nameField)
                        .where(com.mybatisflex.core.query.QueryMethods.column(idField).in(ids));

                // 使用 listAs 方法查询多条记录
                List<Row> rows = iService.listAs(queryWrapper, Row.class);
                for (Row row : rows) {
                    Object id = row.get(idField);
                    String name = row.getString(nameField);
                    if (id != null && name != null) {
                        result.put(id, name);
                    }
                }
            }
        } catch (Exception e) {
            // 如果Service查询失败，尝试直接批量查询
            result.putAll(batchDirectQuery(targetEntity, ids, idField, nameField));
        }

        return result;
    }

    /**
     * 直接批量查询（备用方案）- 修正参数传递方式
     */
    private static Map<Object, String> batchDirectQuery(Class<?> targetEntity, List<Object> ids,
                                                        String idField, String nameField) {
        Map<Object, String> result = new HashMap<>();

        try {
            String tableName = getTableName(targetEntity);
            if (tableName == null) {
                return result;
            }

            // 使用 Mybatis-Flex 的 IN 查询方式
            QueryWrapper queryWrapper = QueryWrapper.create()
                    .select(idField, nameField)
                    .from(tableName)
                    .where(com.mybatisflex.core.query.QueryMethods.column(idField).in(ids));

            // 使用 Db.selectListByQuery 方法
            List<Row> rows = com.mybatisflex.core.row.Db.selectListByQuery(queryWrapper);
            for (Row row : rows) {
                Object id = row.get(idField);
                String name = row.getString(nameField);
                if (id != null && name != null) {
                    result.put(id, name);
                }
            }
        } catch (Exception e) {
            System.err.println("直接批量查询名称失败: " + e.getMessage());
        }

        return result;
    }

    /**
     * 清除缓存
     */
    public static void clearCache() {
        nameCache.clear();
        cacheTimeMap.clear();
    }

    /**
     * 清除指定实体类的缓存
     */
    public static void clearCache(Class<?> targetEntity) {
        String prefix = targetEntity.getSimpleName() + ":";
        nameCache.keySet().removeIf(key -> key.startsWith(prefix));
        cacheTimeMap.keySet().removeIf(key -> key.startsWith(prefix));
    }

    /**
     * 清除表名缓存（主要用于开发环境）
     */
    public static void clearTableNameCache() {
        tableNameCache.clear();
    }

    /**
     * 清除指定实体类的表名缓存
     */
    public static void clearTableNameCache(Class<?> targetEntity) {
        tableNameCache.remove(targetEntity);
    }
}